/*
 * This file is part of b.AMP.
 *
 * b.AMP is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * b.AMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with b.AMP.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __BAMP_LOGGER_HPP__
#define __BAMP_LOGGER_HPP__

#include <boost/filesystem.hpp>
#include <string>
#include <sstream>

namespace bamp
{ 
    /**
     * The Logger is a simple, thread-safe, global logger object.
     */
    class Logger
    {
    public:

        /**
         * Enable/disable output to standard error. This is enabled by
         * default.
         */
        static void setStderr(const bool enable);

        /**
         * Set output file name. Set an empty filename to disable
         * output to a file. This is disabled by default.
         */
        static void setFile(const boost::filesystem::path& filename);

        /**
         * Log a message. This should be done by using one of the
         * utility macros.
         */
        template<typename MsgType>
        static void log(const std::string& prefix, MsgType msg)
        {
            std::ostringstream os;
            os << msg;
            __log(prefix, os.str());
        }

    private:
        static void __log(const std::string& prefix, const std::string& msg);

        struct Implementation;
        static Implementation& impl();

    };
}

/*
 * Simple logging macros. This is the way b.AMP subsystems should log
 * their messages. The actual implementation of these macros may
 * change at any time.
 */

#define BAMP_LOG_LEVEL_TRACE    0
#define BAMP_LOG_LEVEL_DEBUG    1
#define BAMP_LOG_LEVEL_INFO     2
#define BAMP_LOG_LEVEL_WARNING  3
#define BAMP_LOG_LEVEL_ERROR    4
#define BAMP_LOG_LEVEL_FATAL    5

#ifndef BAMP_STATIC_LOG_LEVEL
#define BAMP_STATIC_LOG_LEVEL BAMP_LOG_LEVEL_TRACE
#endif

#define BAMP_LOG(__lvl, __msg) bamp::Logger::log(std::string(__lvl), __msg)

#if BAMP_STATIC_LOG_LEVEL <= BAMP_LOG_LEVEL_TRACE
#define BAMP_LOG_TRACE(__msg) BAMP_LOG("trace", __msg)
#else
#define BAMP_LOG_TRACE
#endif

#if BAMP_STATIC_LOG_LEVEL <= BAMP_LOG_LEVEL_DEBUG
#define BAMP_LOG_DEBUG(__msg) BAMP_LOG("debug", __msg)
#else
#define BAMP_LOG_DEBUG
#endif

#if BAMP_STATIC_LOG_LEVEL <= BAMP_LOG_LEVEL_INFO
#define BAMP_LOG_INFO(__msg) BAMP_LOG("info", __msg)
#else
#define BAMP_LOG_INFO
#endif

#if BAMP_STATIC_LOG_LEVEL <= BAMP_LOG_LEVEL_WARNING
#define BAMP_LOG_WARNING(__msg) BAMP_LOG("warning", __msg)
#else
#define BAMP_LOG_WARNING
#endif

#if BAMP_STATIC_LOG_LEVEL <= BAMP_LOG_LEVEL_ERROR
#define BAMP_LOG_ERROR(__msg) BAMP_LOG("error", __msg)
#else
#define BAMP_LOG_ERROR
#endif

#if BAMP_STATIC_LOG_LEVEL <= BAMP_LOG_LEVEL_FATAL
#define BAMP_LOG_FATAL(__msg) BAMP_LOG("fatal", __msg)
#else
#define BAMP_LOG_FATAL
#endif


#endif // __BAMP_LOGGER_HPP__
